home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / arcers / tarsrc.zip / TARSRC.TAR / tar-1.11.2 / create.c < prev    next >
C/C++ Source or Header  |  1993-11-15  |  36KB  |  1,468 lines

  1. /* Create a tar archive.
  2.    Copyright (C) 1985, 1992, 1993 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Create a tar archive.
  22.  *
  23.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  24.  */
  25.  
  26. #ifdef _AIX
  27.  #pragma alloca
  28. #endif
  29. #include <sys/types.h>
  30. #include <stdio.h>
  31. #include <errno.h>
  32. #ifndef STDC_HEADERS
  33. extern int errno;
  34. #endif
  35.  
  36. #ifdef BSD42
  37. #include <sys/file.h>
  38. #else
  39. #ifndef V7
  40. #include <fcntl.h>
  41. #endif
  42. #endif
  43.  
  44. #include "tar.h"
  45. #include "port.h"
  46.  
  47. #if !defined(__MSDOS__) && !defined(WINDOWSNT)
  48. #include <pwd.h>
  49. #include <grp.h>
  50. #endif
  51.  
  52. #if defined (_POSIX_VERSION)
  53. #include <utime.h>
  54. #elif defined(WINDOWSNT)
  55. #include <sys\utime.h>
  56. #else
  57. struct utimbuf
  58. {
  59.   long actime;
  60.   long modtime;
  61. };
  62.  
  63. #endif
  64.  
  65. extern struct stat hstat;    /* Stat struct corresponding */
  66.  
  67. #if !defined(__MSDOS__) && !defined(WINDOWSNT)
  68. extern dev_t ar_dev;
  69. extern ino_t ar_ino;
  70. #endif
  71.  
  72. /* JF */
  73. extern struct name *gnu_list_name;
  74.  
  75. /*
  76.  * If there are no symbolic links, there is no lstat().  Use stat().
  77.  */
  78. #ifndef S_ISLNK
  79. #define lstat stat
  80. #endif
  81.  
  82. #ifndef USE_PROTOTYPES
  83. extern void print_header ();
  84.  
  85. union record *start_header ();
  86. void blank_name_list ();
  87. int check_exclude ();
  88. PTR ck_malloc ();
  89. PTR ck_realloc ();
  90. void clear_buffer ();
  91. void close_archive ();
  92. void collect_and_sort_names ();
  93. int confirm ();
  94. int deal_with_sparse ();
  95. void find_new_file_size ();
  96. void finish_header ();
  97. int finish_sparse_file ();
  98. void finduname ();
  99. void findgname ();
  100. int is_dot_or_dotdot ();
  101. void open_archive ();
  102. char *name_next ();
  103. void name_close ();
  104. void to_oct ();
  105. void dump_file ();
  106. void write_dir_file ();
  107. void write_eot ();
  108. void write_long ();
  109. int zero_record ();
  110. #else
  111. #include "create_p.h"
  112. #include "buffer_p.h"
  113. #include "port_p.h"
  114. #include "tar_p.h"
  115. #include "gnu_p.h"
  116. #include "list_p.h"
  117. #endif
  118.  
  119. /* This code moved from tar.h since create.c is the only file that cares
  120.    about 'struct link's.  This means that other files might not have to
  121.    include sys/types.h any more. */
  122.  
  123. struct link
  124.   {
  125.     struct link *next;
  126.     dev_t dev;
  127.     ino_t ino;
  128.     short linkcount;
  129.     char name[1];
  130.   };
  131.  
  132. struct link *linklist;        /* Points to first link in list */
  133.  
  134. static nolinks;            /* Gets set if we run out of RAM */
  135.  
  136. /*
  137.  * "Scratch" space to store the information about a sparse file before
  138.  * writing the info into the header or extended header
  139.  */
  140. /* struct sp_array     *sparsearray;*/
  141.  
  142. /* number of elts storable in the sparsearray */
  143. /*int     sparse_array_size = 10;*/
  144.  
  145. void
  146. create_archive ()
  147. {
  148.   register char *p;
  149.   char *name_from_list ();
  150.  
  151.   open_archive (0);        /* Open for writing */
  152.  
  153.   if (f_gnudump)
  154.     {
  155.       char *buf = ck_malloc (PATH_MAX);
  156.       char *q, *bufp;
  157.  
  158.       collect_and_sort_names ();
  159.  
  160.       while (p = name_from_list ())
  161.     dump_file (p, -1, 1);
  162.       /* if(!f_dironly) { */
  163.       blank_name_list ();
  164.       while (p = name_from_list ())
  165.     {
  166.       strcpy (buf, p);
  167.       if (p[strlen (p) - 1] != '/')
  168.         strcat (buf, "/");
  169.       bufp = buf + strlen (buf);
  170.       for (q = gnu_list_name->dir_contents; q && *q; q += strlen (q) + 1)
  171.         {
  172.           if (*q == 'Y')
  173.         {
  174.           strcpy (bufp, q + 1);
  175.           dump_file (buf, -1, 1);
  176.         }
  177.         }
  178.     }
  179.       /* } */
  180.       free (buf);
  181.     }
  182.   else
  183.     {
  184.       while (p = name_next (1))
  185.     dump_file (p, -1, 1);
  186.     }
  187.  
  188.   write_eot ();
  189.   close_archive ();
  190.   if (f_gnudump)
  191.     write_dir_file ();
  192.   name_close ();
  193. }
  194.  
  195. /*
  196.  * Dump a single file.  If it's a directory, recurse.
  197.  * Result is 1 for success, 0 for failure.
  198.  * Sets global "hstat" to stat() output for this file.
  199.  */
  200. void
  201. dump_file (p, curdev, toplevel)
  202.      char *p;            /* File name to dump */
  203.      int curdev;        /* Device our parent dir was on */
  204.      int toplevel;        /* Whether we are a toplevel call */
  205. {
  206.   union record *header;
  207.   char type;
  208.   extern char *save_name;    /* JF for multi-volume support */
  209.   extern long save_totsize;
  210.   extern long save_sizeleft;
  211.   union record *exhdr;
  212.   char save_linkflag;
  213.   extern time_t new_time;
  214.   int critical_error = 0;
  215.   struct utimbuf restore_times;
  216.   /*    int sparse_ind = 0;*/
  217.  
  218.  
  219.   if (f_confirm && !confirm ("add", p))
  220.     return;
  221.  
  222.   /*
  223.      * Use stat if following (rather than dumping) 4.2BSD's
  224.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  225.      * systems, is #define'd to stat anyway.
  226.      */
  227. #ifdef STX_HIDDEN        /* AIX */
  228.   if (0 != f_follow_links ?
  229.       statx (p, &hstat, STATSIZE, STX_HIDDEN) :
  230.       statx (p, &hstat, STATSIZE, STX_HIDDEN | STX_LINK))
  231. #else
  232.   if (0 != f_follow_links ? stat (p, &hstat) : lstat (p, &hstat))
  233. #endif
  234.     {
  235.     badperror:
  236.       msg_perror ("can't add file %s", p);
  237.     badfile:
  238.       if (!f_ignore_failed_read || critical_error)
  239.     errors++;
  240.       return;
  241.     }
  242.  
  243.   restore_times.actime = hstat.st_atime;
  244.   restore_times.modtime = hstat.st_mtime;
  245.  
  246. #ifdef S_ISHIDDEN
  247.   if (S_ISHIDDEN (hstat.st_mode))
  248.     {
  249.       char *new = (char *) alloca (strlen (p) + 2);
  250.       if (new)
  251.     {
  252.       strcpy (new, p);
  253.       strcat (new, "@");
  254.       p = new;
  255.     }
  256.     }
  257. #endif
  258.  
  259.   /* See if we only want new files, and check if this one is too old to
  260.        put in the archive. */
  261.   if (f_new_files
  262.       && !f_gnudump
  263.       && new_time > hstat.st_mtime
  264.       && !S_ISDIR (hstat.st_mode)
  265.       && (f_new_files > 1 || new_time > hstat.st_ctime))
  266.     {
  267.       if (curdev == -1)
  268.     {
  269.       msg ("%s: is unchanged; not dumped", p);
  270.     }
  271.       return;
  272.     }
  273.  
  274. #if !defined(__MSDOS__) && !defined(WINDOWSNT)
  275.   /* See if we are trying to dump the archive */
  276.   if (ar_dev && hstat.st_dev == ar_dev && hstat.st_ino == ar_ino)
  277.     {
  278.       msg ("%s is the archive; not dumped", p);
  279.       return;
  280.     }
  281. #endif
  282.   /*
  283.      * Check for multiple links.
  284.      *
  285.      * We maintain a list of all such files that we've written so
  286.      * far.  Any time we see another, we check the list and
  287.      * avoid dumping the data again if we've done it once already.
  288.      */
  289.   if (hstat.st_nlink > 1
  290.       && (S_ISREG (hstat.st_mode)
  291. #ifdef S_ISCTG
  292.       || S_ISCTG (hstat.st_mode)
  293. #endif
  294. #ifdef S_ISCHR
  295.       || S_ISCHR (hstat.st_mode)
  296. #endif
  297. #ifdef S_ISBLK
  298.       || S_ISBLK (hstat.st_mode)
  299. #endif
  300. #ifdef S_ISFIFO
  301.       || S_ISFIFO (hstat.st_mode)
  302. #endif
  303.       ))
  304.     {
  305.       register struct link *lp;
  306.  
  307.       /* First quick and dirty.  Hashing, etc later FIXME */
  308.       for (lp = linklist; lp; lp = lp->next)
  309.     {
  310.       if (lp->ino == hstat.st_ino &&
  311.           lp->dev == hstat.st_dev)
  312.         {
  313.           char *link_name = lp->name;
  314.  
  315.           /* We found a link. */
  316.           while (!f_absolute_paths && *link_name == '/')
  317.         {
  318.           static int link_warn = 0;
  319.  
  320.           if (!link_warn)
  321.             {
  322.               msg ("Removing leading / from absolute links");
  323.               link_warn++;
  324.             }
  325.           link_name++;
  326.         }
  327.           if (link_name - lp->name >= NAMSIZ)
  328.         write_long (link_name, LF_LONGLINK);
  329.           current_link_name = link_name;
  330.  
  331.           hstat.st_size = 0;
  332.           header = start_header (p, &hstat);
  333.           if (header == NULL)
  334.         {
  335.           critical_error = 1;
  336.           goto badfile;
  337.         }
  338.           strncpy (header->header.arch_linkname,
  339.                link_name, NAMSIZ);
  340.  
  341.           /* Force null truncated */
  342.           header->header.arch_linkname[NAMSIZ - 1] = 0;
  343.  
  344.           header->header.linkflag = LF_LINK;
  345.           finish_header (header);
  346.           /* FIXME: Maybe remove from list after all links found? */
  347.           if (f_remove_files)
  348.         {
  349.           if (unlink (p) == -1)
  350.             msg_perror ("cannot remove %s", p);
  351.         }
  352.           return;        /* We dumped it */
  353.         }
  354.     }
  355.  
  356.       /* Not found.  Add it to the list of possible links. */
  357.       lp = (struct link *) ck_malloc ((unsigned) (sizeof (struct link) + strlen (p)));
  358.       if (!lp)
  359.     {
  360.       if (!nolinks)
  361.         {
  362.           msg (
  363.           "no memory for links, they will be dumped as separate files");
  364.           nolinks++;
  365.         }
  366.     }
  367.       lp->ino = hstat.st_ino;
  368.       lp->dev = hstat.st_dev;
  369.       strcpy (lp->name, p);
  370.       lp->next = linklist;
  371.       linklist = lp;
  372.     }
  373.  
  374.   /*
  375.      * This is not a link to a previously dumped file, so dump it.
  376.      */
  377.   if (S_ISREG (hstat.st_mode)
  378. #ifdef S_ISCTG
  379.       || S_ISCTG (hstat.st_mode)
  380. #endif
  381.     )
  382.     {
  383.       int f;            /* File descriptor */
  384.       long bufsize, count;
  385.       long sizeleft;
  386.       register union record *start;
  387.       int header_moved;
  388.       char isextended = 0;
  389.       int upperbound;
  390.       /*        int    end_nulls = 0; */
  391.  
  392.       header_moved = 0;
  393.  
  394. #ifdef BSD42
  395.       if (f_sparse_files)
  396.     {
  397.       /*
  398.           * JK - This is the test for sparseness: whether the
  399.          * "size" of the file matches the number of blocks
  400.          * allocated for it.  If there is a smaller number
  401.          * of blocks that would be necessary to accommodate
  402.          * a file of this size, we have a sparse file, i.e.,
  403.          * at least one of those records in the file is just
  404.          * a useless hole.
  405.          */
  406. #ifdef hpux            /* Nice of HPUX to gratuitiously change it, huh?  - mib */
  407.       if (hstat.st_size - (hstat.st_blocks * 1024) > 1024)
  408. #else
  409.       if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE)
  410. #endif
  411.         {
  412.           int filesize = hstat.st_size;
  413.           register int i;
  414.  
  415.           header = start_header (p, &hstat);
  416.           if (header == NULL)
  417.         {
  418.           critical_error = 1;
  419.           goto badfile;
  420.         }
  421.           header->header.linkflag = LF_SPARSE;
  422.           header_moved++;
  423.  
  424.           /*
  425.              * Call the routine that figures out the
  426.              * layout of the sparse file in question.
  427.              * UPPERBOUND is the index of the last
  428.              * element of the "sparsearray," i.e.,
  429.              * the number of elements it needed to
  430.              * describe the file.
  431.              */
  432.  
  433.           upperbound = deal_with_sparse (p, header);
  434.  
  435.           /*
  436.              * See if we'll need an extended header
  437.              * later
  438.              */
  439.           if (upperbound > SPARSE_IN_HDR - 1)
  440.         header->header.isextended++;
  441.           /*
  442.              * We store the "real" file size so
  443.              * we can show that in case someone wants
  444.              * to list the archive, i.e., tar tvf <file>.
  445.              * It might be kind of disconcerting if the
  446.              * shrunken file size was the one that showed
  447.              * up.
  448.              */
  449.           to_oct ((long) hstat.st_size, 1 + 12,
  450.               header->header.realsize);
  451.  
  452.           /*
  453.              * This will be the new "size" of the
  454.              * file, i.e., the size of the file
  455.              * minus the records of holes that we're
  456.              * skipping over.
  457.              */
  458.  
  459.           find_new_file_size (&filesize, upperbound);
  460.           hstat.st_size = filesize;
  461.           to_oct ((long) filesize, 1 + 12,
  462.               header->header.size);
  463.           /*                to_oct((long) end_nulls, 1+12,
  464.                         header->header.ending_blanks);*/
  465.  
  466.           for (i = 0; i < SPARSE_IN_HDR; i++)
  467.         {
  468.           if (!sparsearray[i].numbytes)
  469.             break;
  470.           to_oct (sparsearray[i].offset, 1 + 12,
  471.               header->header.sp[i].offset);
  472.           to_oct (sparsearray[i].numbytes, 1 + 12,
  473.               header->header.sp[i].numbytes);
  474.         }
  475.  
  476.         }
  477.     }
  478. #else
  479.       upperbound = SPARSE_IN_HDR - 1;
  480. #endif
  481.  
  482.       sizeleft = hstat.st_size;
  483.       /* Don't bother opening empty, world readable files. */
  484.       if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode))
  485.     {
  486.       f = open (p, O_RDONLY | O_BINARY);
  487.       if (f < 0)
  488.         goto badperror;
  489.     }
  490.       else
  491.     {
  492.       f = -1;
  493.     }
  494.  
  495.       /* If the file is sparse, we've already taken care of this */
  496.       if (!header_moved)
  497.     {
  498.       header = start_header (p, &hstat);
  499.       if (header == NULL)
  500.         {
  501.           if (f >= 0)
  502.         (void) close (f);
  503.           critical_error = 1;
  504.           goto badfile;
  505.         }
  506.     }
  507. #ifdef S_ISCTG
  508.       /* Mark contiguous files, if we support them */
  509.       if (f_standard && S_ISCTG (hstat.st_mode))
  510.     {
  511.       header->header.linkflag = LF_CONTIG;
  512.     }
  513. #endif
  514.       isextended = header->header.isextended;
  515.       save_linkflag = header->header.linkflag;
  516.       finish_header (header);
  517.       if (isextended)
  518.     {
  519.       /*            int     sum = 0;*/
  520.       register int i;
  521.       /*            register union record *exhdr;*/
  522.       /*            int     arraybound = SPARSE_EXT_HDR;*/
  523.       /* static */ int index_offset = SPARSE_IN_HDR;
  524.  
  525.     extend:exhdr = findrec ();
  526.  
  527.       if (exhdr == NULL)
  528.         {
  529.           critical_error = 1;
  530.           goto badfile;
  531.         }
  532.       bzero (exhdr->charptr, RECORDSIZE);
  533.       for (i = 0; i < SPARSE_EXT_HDR; i++)
  534.         {
  535.           if (i + index_offset > upperbound)
  536.         break;
  537.           to_oct ((long) sparsearray[i + index_offset].numbytes,
  538.               1 + 12,
  539.               exhdr->ext_hdr.sp[i].numbytes);
  540.           to_oct ((long) sparsearray[i + index_offset].offset,
  541.               1 + 12,
  542.               exhdr->ext_hdr.sp[i].offset);
  543.         }
  544.       userec (exhdr);
  545.       /*            sum += i;
  546.             if (sum < upperbound)
  547.                 goto extend;*/
  548.       if (index_offset + i <= upperbound)
  549.         {
  550.           index_offset += i;
  551.           exhdr->ext_hdr.isextended++;
  552.           goto extend;
  553.         }
  554.  
  555.     }
  556.       if (save_linkflag == LF_SPARSE)
  557.     {
  558.       if (finish_sparse_file (f, &sizeleft, hstat.st_size, p))
  559.         goto padit;
  560.     }
  561.       else
  562.     while (sizeleft > 0)
  563.       {
  564.  
  565.         if (f_multivol)
  566.           {
  567.         save_name = p;
  568.         save_sizeleft = sizeleft;
  569.         save_totsize = hstat.st_size;
  570.           }
  571.         start = findrec ();
  572.  
  573.         bufsize = endofrecs ()->charptr - start->charptr;
  574.  
  575.         if (sizeleft < bufsize)
  576.           {
  577.         /* Last read -- zero out area beyond */
  578.         bufsize = (int) sizeleft;
  579.         count = bufsize % RECORDSIZE;
  580.         if (count)
  581.           bzero (start->charptr + sizeleft,
  582.              (int) (RECORDSIZE - count));
  583.           }
  584.         count = read (f, start->charptr, bufsize);
  585.         if (count < 0)
  586.           {
  587.         msg_perror ("read error at byte %ld, reading\
  588.  %d bytes, in file %s", hstat.st_size - sizeleft, bufsize, p);
  589.         goto padit;
  590.           }
  591.         sizeleft -= count;
  592.  
  593.         /* This is nonportable (the type of userec's arg). */
  594.         userec (start + (count - 1) / RECORDSIZE);
  595.  
  596.         if (count == bufsize)
  597.           continue;
  598.         msg ("file %s shrunk by %d bytes, padding with zeros.", p, sizeleft);
  599.         goto padit;        /* Short read */
  600.       }
  601.  
  602.       if (f_multivol)
  603.     save_name = 0;
  604.  
  605.       if (f >= 0)
  606.     (void) close (f);
  607.  
  608.       if (f_remove_files)
  609.     {
  610.       if (unlink (p) == -1)
  611.         msg_perror ("cannot remove %s", p);
  612.     }
  613.       if (f_atime_preserve)
  614.     utime (p, &restore_times);
  615.       return;
  616.  
  617.       /*
  618.          * File shrunk or gave error, pad out tape to match
  619.          * the size we specified in the header.
  620.          */
  621.     padit:
  622.       while (sizeleft > 0)
  623.     {
  624.       save_sizeleft = sizeleft;
  625.       start = findrec ();
  626.       bzero (start->charptr, RECORDSIZE);
  627.       userec (start);
  628.       sizeleft -= RECORDSIZE;
  629.     }
  630.       if (f_multivol)
  631.     save_name = 0;
  632.       if (f >= 0)
  633.     (void) close (f);
  634.       if (f_atime_preserve)
  635.     utime (p, &restore_times);
  636.       return;
  637.     }
  638.  
  639. #ifdef S_ISLNK
  640.   else if (S_ISLNK (hstat.st_mode))
  641.     {
  642.       int size;
  643.       char *buf = alloca (PATH_MAX + 1);
  644.  
  645.       size = readlink (p, buf, PATH_MAX + 1);
  646.       if (size < 0)
  647.     goto badperror;
  648.       buf[size] = '\0';
  649.       if (size >= NAMSIZ)
  650.     write_long (buf, LF_LONGLINK);
  651.       current_link_name = buf;
  652.  
  653.       hstat.st_size = 0;    /* Force 0 size on symlink */
  654.       header = start_header (p, &hstat);
  655.       if (header == NULL)
  656.     {
  657.       critical_error = 1;
  658.       goto badfile;
  659.     }
  660.       strncpy (header->header.arch_linkname, buf, NAMSIZ);
  661.       header->header.arch_linkname[NAMSIZ - 1] = '\0';
  662.       header->header.linkflag = LF_SYMLINK;
  663.       finish_header (header);    /* Nothing more to do to it */
  664.       if (f_remove_files)
  665.     {
  666.       if (unlink (p) == -1)
  667.         msg_perror ("cannot remove %s", p);
  668.     }
  669.       return;
  670.     }
  671. #endif
  672.  
  673.   else if (S_ISDIR (hstat.st_mode))
  674.     {
  675.       register DIR *dirp;
  676.       register struct dirent *d;
  677.       char *namebuf;
  678.       int buflen;
  679.       register int len;
  680.       int our_device = hstat.st_dev;
  681.  
  682.       /* Build new prototype name */
  683.       len = strlen (p);
  684.       buflen = len + NAMSIZ;
  685.       namebuf = ck_malloc (buflen + 1);
  686.       strncpy (namebuf, p, buflen);
  687.       while (len >= 1 && '/' == namebuf[len - 1])
  688.     len--;            /* Delete trailing slashes */
  689.       namebuf[len++] = '/';    /* Now add exactly one back */
  690.       namebuf[len] = '\0';    /* Make sure null-terminated */
  691.  
  692.       /*
  693.          * Output directory header record with permissions
  694.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  695.          * If old archive format, don't write record at all.
  696.          */
  697.       if (!f_oldarch)
  698.     {
  699.       hstat.st_size = 0;    /* Force 0 size on dir */
  700.       /*
  701.              * If people could really read standard archives,
  702.              * this should be:        (FIXME)
  703.             header = start_header(f_standard? p: namebuf, &hstat);
  704.              * but since they'd interpret LF_DIR records as
  705.              * regular files, we'd better put the / on the name.
  706.              */
  707.       header = start_header (namebuf, &hstat);
  708.       if (header == NULL)
  709.         {
  710.           critical_error = 1;
  711.           goto badfile;    /* eg name too long */
  712.         }
  713.  
  714.       if (f_gnudump)
  715.         header->header.linkflag = LF_DUMPDIR;
  716.       else if (f_standard)
  717.         header->header.linkflag = LF_DIR;
  718.  
  719.       /* If we're gnudumping, we aren't done yet so don't close it. */
  720.       if (!f_gnudump)
  721.         finish_header (header);    /* Done with directory header */
  722.     }
  723.  
  724.       if (f_gnudump)
  725.     {
  726.       int sizeleft;
  727.       int totsize;
  728.       int bufsize;
  729.       union record *start;
  730.       int count;
  731.       char *buf, *p_buf;
  732.  
  733.       buf = gnu_list_name->dir_contents;    /* FOO */
  734.       totsize = 0;
  735.       for (p_buf = buf; p_buf && *p_buf;)
  736.         {
  737.           int tmp;
  738.  
  739.           tmp = strlen (p_buf) + 1;
  740.           totsize += tmp;
  741.           p_buf += tmp;
  742.         }
  743.       totsize++;
  744.       to_oct ((long) totsize, 1 + 12, header->header.size);
  745.       finish_header (header);
  746.       p_buf = buf;
  747.       sizeleft = totsize;
  748.       while (sizeleft > 0)
  749.         {
  750.           if (f_multivol)
  751.         {
  752.           save_name = p;
  753.           save_sizeleft = sizeleft;
  754.           save_totsize = totsize;
  755.         }
  756.           start = findrec ();
  757.           bufsize = endofrecs ()->charptr - start->charptr;
  758.           if (sizeleft < bufsize)
  759.         {
  760.           bufsize = sizeleft;
  761.           count = bufsize % RECORDSIZE;
  762.           if (count)
  763.             bzero (start->charptr + sizeleft, RECORDSIZE - count);
  764.         }
  765.           bcopy (p_buf, start->charptr, bufsize);
  766.           sizeleft -= bufsize;
  767.           p_buf += bufsize;
  768.           userec (start + (bufsize - 1) / RECORDSIZE);
  769.         }
  770.       if (f_multivol)
  771.         save_name = 0;
  772.       if (f_atime_preserve)
  773.         utime (p, &restore_times);
  774.       return;
  775.     }
  776.  
  777.       /* Now output all the files in the directory */
  778. #if 0
  779.       if (f_dironly)
  780.     return;            /* Unless the cmdline said not to */
  781. #endif
  782.       /*
  783.          * See if we are crossing from one file system to another,
  784.          * and avoid doing so if the user only wants to dump one file system.
  785.          */
  786.       if (f_local_filesys && !toplevel && curdev != hstat.st_dev)
  787.     {
  788.       if (f_verbose)
  789.         msg ("%s: is on a different filesystem; not dumped", p);
  790.       return;
  791.     }
  792.  
  793.  
  794.       errno = 0;
  795.       dirp = opendir (p);
  796.       if (!dirp)
  797.     {
  798.       if (errno)
  799.         {
  800.           msg_perror ("can't open directory %s", p);
  801.         }
  802.       else
  803.         {
  804.           msg ("error opening directory %s",
  805.            p);
  806.         }
  807.       return;
  808.     }
  809.  
  810.       /* Hack to remove "./" from the front of all the file names */
  811.       if (len == 2 && namebuf[0] == '.' && namebuf[1] == '/')
  812.     len = 0;
  813.  
  814.       /* Should speed this up by cd-ing into the dir, FIXME */
  815.       while (NULL != (d = readdir (dirp)))
  816.     {
  817.       /* Skip . and .. */
  818.       if (is_dot_or_dotdot (d->d_name))
  819.         continue;
  820.  
  821.       if (NLENGTH (d) + len >= buflen)
  822.         {
  823.           buflen = len + NLENGTH (d);
  824.           namebuf = ck_realloc (namebuf, buflen + 1);
  825.           /* namebuf[len]='\0';
  826.                 msg("file name %s%s too long",
  827.                     namebuf, d->d_name);
  828.                 continue; */
  829.         }
  830.       strcpy (namebuf + len, d->d_name);
  831.       if (f_exclude && check_exclude (namebuf))
  832.         continue;
  833.       dump_file (namebuf, our_device, 0);
  834.     }
  835.  
  836.       closedir (dirp);
  837.       free (namebuf);
  838.       if (f_atime_preserve)
  839.     utime (p, &restore_times);
  840.       return;
  841.     }
  842.  
  843. #ifdef S_ISCHR
  844.   else if (S_ISCHR (hstat.st_mode))
  845.     {
  846.       type = LF_CHR;
  847.     }
  848. #endif
  849.  
  850. #ifdef S_ISBLK
  851.   else if (S_ISBLK (hstat.st_mode))
  852.     {
  853.       type = LF_BLK;
  854.     }
  855. #endif
  856.  
  857.   /* Avoid screwy apollo lossage where S_IFIFO == S_IFSOCK */
  858. #if (_ISP__M68K == 0) && (_ISP__A88K == 0) && defined(S_ISFIFO)
  859.   else if (S_ISFIFO (hstat.st_mode))
  860.     {
  861.       type = LF_FIFO;
  862.     }
  863. #endif
  864.  
  865. #ifdef S_ISSOCK
  866.   else if (S_ISSOCK (hstat.st_mode))
  867.     {
  868.       type = LF_FIFO;
  869.     }
  870. #endif
  871.   else
  872.     goto unknown;
  873.  
  874.   if (!f_standard)
  875.     goto unknown;
  876.  
  877.   hstat.st_size = 0;        /* Force 0 size */
  878.   header = start_header (p, &hstat);
  879.   if (header == NULL)
  880.     {
  881.       critical_error = 1;
  882.       goto badfile;        /* eg name too long */
  883.     }
  884.  
  885.   header->header.linkflag = type;
  886. #if defined(S_IFBLK) || defined(S_IFCHR)
  887.   if (type != LF_FIFO)
  888.     {
  889.       to_oct ((long) major (hstat.st_rdev), 8,
  890.           header->header.devmajor);
  891.       to_oct ((long) minor (hstat.st_rdev), 8,
  892.           header->header.devminor);
  893.     }
  894. #endif
  895.  
  896.   finish_header (header);
  897.   if (f_remove_files)
  898.     {
  899.       if (unlink (p) == -1)
  900.     msg_perror ("cannot remove %s", p);
  901.     }
  902.   return;
  903.  
  904. unknown:
  905.   msg ("%s: Unknown file type; file ignored.", p);
  906. }
  907.  
  908. int
  909. finish_sparse_file (fd, sizeleft, fullsize, name)
  910.      int fd;
  911.      long *sizeleft, fullsize;
  912.      char *name;
  913. {
  914.   union record *start;
  915.   char tempbuf[RECORDSIZE];
  916.   int bufsize, sparse_ind = 0, count;
  917.   long pos;
  918.   long nwritten = 0;
  919.  
  920.  
  921.   while (*sizeleft > 0)
  922.     {
  923.       start = findrec ();
  924.       bzero (start->charptr, RECORDSIZE);
  925.       bufsize = sparsearray[sparse_ind].numbytes;
  926.       if (!bufsize)
  927.     {            /* we blew it, maybe */
  928.       msg ("Wrote %ld of %ld bytes to file %s",
  929.            fullsize - *sizeleft, fullsize, name);
  930.       break;
  931.     }
  932.       pos = lseek (fd, sparsearray[sparse_ind++].offset, 0);
  933.       /*
  934.          * If the number of bytes to be written here exceeds
  935.          * the size of the temporary buffer, do it in steps.
  936.          */
  937.       while (bufsize > RECORDSIZE)
  938.     {
  939.       /*            if (amt_read) {
  940.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  941.                 bufsize -= RECORDSIZE - amt_read;
  942.                 amt_read = 0;
  943.                 userec(start);
  944.                 start = findrec();
  945.                 bzero(start->charptr, RECORDSIZE);
  946.             }*/
  947.       /* store the data */
  948.       count = read (fd, start->charptr, RECORDSIZE);
  949.       if (count < 0)
  950.         {
  951.           msg_perror ("read error at byte %ld, reading %d bytes, in file %s",
  952.               fullsize - *sizeleft, bufsize, name);
  953.           return 1;
  954.         }
  955.       bufsize -= count;
  956.       *sizeleft -= count;
  957.       userec (start);
  958.       nwritten += RECORDSIZE;    /* XXX */
  959.       start = findrec ();
  960.       bzero (start->charptr, RECORDSIZE);
  961.     }
  962.  
  963.  
  964.       clear_buffer (tempbuf);
  965.       count = read (fd, tempbuf, bufsize);
  966.       bcopy (tempbuf, start->charptr, RECORDSIZE);
  967.       if (count < 0)
  968.     {
  969.       msg_perror ("read error at byte %ld, reading %d bytes, in file %s",
  970.               fullsize - *sizeleft, bufsize, name);
  971.       return 1;
  972.     }
  973.       /*        if (amt_read >= RECORDSIZE) {
  974.             amt_read = 0;
  975.             userec(start+(count-1)/RECORDSIZE);
  976.             if (count != bufsize) {
  977.                 msg("file %s shrunk by %d bytes, padding with zeros.", name, sizeleft);
  978.                 return 1;
  979.             }
  980.             start = findrec();
  981.         } else
  982.             amt_read += bufsize;*/
  983.       nwritten += count;    /* XXX */
  984.       *sizeleft -= count;
  985.       userec (start);
  986.  
  987.     }
  988.   free (sparsearray);
  989.   /*    printf ("Amount actually written is (I hope) %d.\n", nwritten); */
  990.   /*    userec(start+(count-1)/RECORDSIZE);*/
  991.   return 0;
  992.  
  993. }
  994.  
  995. void
  996. init_sparsearray ()
  997. {
  998.   register int i;
  999.  
  1000.   sp_array_size = 10;
  1001.   /*
  1002.      * Make room for our scratch space -- initially is 10 elts long
  1003.      */
  1004.   sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
  1005.   for (i = 0; i < sp_array_size; i++)
  1006.     {
  1007.       sparsearray[i].offset = 0;
  1008.       sparsearray[i].numbytes = 0;
  1009.     }
  1010. }
  1011.  
  1012.  
  1013.  
  1014. /*
  1015.  * Okay, we've got a sparse file on our hands -- now, what we need to do is
  1016.  * make a pass through the file and carefully note where any data is, i.e.,
  1017.  * we want to find how far into the file each instance of data is, and how
  1018.  * many bytes are there.  We store this information in the sparsearray,
  1019.  * which will later be translated into header information.  For now, we use
  1020.  * the sparsearray as convenient storage.
  1021.  *
  1022.  * As a side note, this routine is a mess.  If I could have found a cleaner
  1023.  * way to do it, I would have.  If anyone wants to find a nicer way to do
  1024.  * this, feel free.
  1025.  */
  1026.  
  1027. /* There is little point in trimming small amounts of null data at the */
  1028. /* head and tail of blocks -- it's ok if we only avoid dumping blocks */
  1029. /* of complete null data */
  1030. int
  1031. deal_with_sparse (name, header, nulls_at_end)
  1032.      char *name;
  1033.      union record *header;
  1034.      int nulls_at_end;
  1035. {
  1036.   long numbytes = 0;
  1037.   long offset = 0;
  1038.   /*    long    save_offset;*/
  1039.   int fd;
  1040.   /*    int    current_size = hstat.st_size;*/
  1041.   int sparse_ind = 0, cc;
  1042.   char buf[RECORDSIZE];
  1043. #if 0
  1044.   int read_last_data = 0;    /* did we just read the last record? */
  1045. #endif
  1046.   int amidst_data = 0;
  1047.  
  1048.   header->header.isextended = 0;
  1049.   /*
  1050.      * Can't open the file -- this problem will be caught later on,
  1051.      * so just return.
  1052.      */
  1053.   if ((fd = open (name, O_RDONLY)) < 0)
  1054.     return 0;
  1055.  
  1056.   init_sparsearray ();
  1057.   clear_buffer (buf);
  1058.  
  1059.   while ((cc = read (fd, buf, sizeof buf)) != 0)
  1060.     {
  1061.  
  1062.       if (sparse_ind > sp_array_size - 1)
  1063.     {
  1064.  
  1065.       /*
  1066.          * realloc the scratch area, since we've run out of room --
  1067.          */
  1068.       sparsearray = (struct sp_array *)
  1069.         ck_realloc (sparsearray,
  1070.              2 * sp_array_size * (sizeof (struct sp_array)));
  1071.       sp_array_size *= 2;
  1072.     }
  1073.       if (cc == sizeof buf)
  1074.     {
  1075.       if (zero_record (buf))
  1076.         {
  1077.           if (amidst_data)
  1078.         {
  1079.           sparsearray[sparse_ind++].numbytes
  1080.             = numbytes;
  1081.           amidst_data = 0;
  1082.         }
  1083.         }
  1084.       else
  1085.         {            /* !zero_record(buf) */
  1086.           if (amidst_data)
  1087.         numbytes += cc;
  1088.           else
  1089.         {
  1090.           amidst_data = 1;
  1091.           numbytes = cc;
  1092.           sparsearray[sparse_ind].offset
  1093.             = offset;
  1094.         }
  1095.         }
  1096.     }
  1097.       else if (cc < sizeof buf)
  1098.     {
  1099.       /* This has to be the last bit of the file, so this */
  1100.       /* is somewhat shorter than the above. */
  1101.       if (!zero_record (buf))
  1102.         {
  1103.           if (!amidst_data)
  1104.         {
  1105.           amidst_data = 1;
  1106.           numbytes = cc;
  1107.           sparsearray[sparse_ind].offset
  1108.             = offset;
  1109.         }
  1110.           else
  1111.         numbytes += cc;
  1112.         }
  1113.     }
  1114.       offset += cc;
  1115.       clear_buffer (buf);
  1116.     }
  1117.   if (amidst_data)
  1118.     sparsearray[sparse_ind++].numbytes = numbytes;
  1119.   else
  1120.     {
  1121.       sparsearray[sparse_ind].offset = offset-1;
  1122.       sparsearray[sparse_ind++].numbytes = 1;
  1123.     }
  1124.   close (fd);
  1125.  
  1126.   return sparse_ind - 1;
  1127. }
  1128.  
  1129. /*
  1130.  * Just zeroes out the buffer so we don't confuse ourselves with leftover
  1131.  * data.
  1132.  */
  1133. void
  1134. clear_buffer (buf)
  1135.      char *buf;
  1136. {
  1137.   register int i;
  1138.  
  1139.   for (i = 0; i < RECORDSIZE; i++)
  1140.     buf[i] = '\0';
  1141. }
  1142.  
  1143. #if 0                /* I'm leaving this as a monument to Joy Kendall, who wrote it -mib */
  1144. /*
  1145.  * JK -
  1146.  * This routine takes a character array, and tells where within that array
  1147.  * the data can be found.  It skips over any zeros, and sets the first
  1148.  * non-zero point in the array to be the "start", and continues until it
  1149.  * finds non-data again, which is marked as the "end."  This routine is
  1150.  * mainly for 1) seeing how far into a file we must lseek to data, given
  1151.  * that we have a sparse file, and 2) determining the "real size" of the
  1152.  * file, i.e., the number of bytes in the sparse file that are data, as
  1153.  * opposed to the zeros we are trying to skip.
  1154.  */
  1155. void
  1156. where_is_data (from, to, buffer)
  1157.      int *from, *to;
  1158.      char *buffer;
  1159. {
  1160.   register int i = 0;
  1161.   register int save_to = *to;
  1162.   int amidst_data = 0;
  1163.  
  1164.  
  1165.   while (!buffer[i])
  1166.     i++;
  1167.   *from = i;
  1168.  
  1169.   if (*from < 16)        /* don't bother */
  1170.     *from = 0;
  1171.   /* keep going to make sure there isn't more real
  1172.        data in this record */
  1173.   while (i < RECORDSIZE)
  1174.     {
  1175.       if (!buffer[i])
  1176.     {
  1177.       if (amidst_data)
  1178.         {
  1179.           save_to = i;
  1180.           amidst_data = 0;
  1181.         }
  1182.       i++;
  1183.     }
  1184.       else if (buffer[i])
  1185.     {
  1186.       if (!amidst_data)
  1187.         amidst_data = 1;
  1188.       i++;
  1189.     }
  1190.     }
  1191.   if (i == RECORDSIZE)
  1192.     *to = i;
  1193.   else
  1194.     *to = save_to;
  1195.  
  1196. }
  1197.  
  1198. #endif
  1199.  
  1200. /* Note that this routine is only called if zero_record returned true */
  1201. #if 0                /* But we actually don't need it at all. */
  1202. void
  1203. where_is_data (from, to, buffer)
  1204.      int *from, *to;
  1205.      char *buffer;
  1206. {
  1207.   char *fp, *tp;
  1208.  
  1209.   for (fp = buffer; !*fp; fp++)
  1210.     ;
  1211.   for (tp = buffer + RECORDSIZE - 1; !*tp; tp--)
  1212.     ;
  1213.   *from = fp - buffer;
  1214.   *to = tp - buffer + 1;
  1215. }
  1216.  
  1217. #endif
  1218.  
  1219.  
  1220.  
  1221. /*
  1222.  * Takes a recordful of data and basically cruises through it to see if
  1223.  * it's made *entirely* of zeros, returning a 0 the instant it finds
  1224.  * something that is a non-zero, i.e., useful data.
  1225.  */
  1226. int
  1227. zero_record (buffer)
  1228.      char *buffer;
  1229. {
  1230.   register int i;
  1231.  
  1232.   for (i = 0; i < RECORDSIZE; i++)
  1233.     if (buffer[i] != '\000')
  1234.       return 0;
  1235.   return 1;
  1236. }
  1237.  
  1238. void
  1239. find_new_file_size (filesize, highest_index)
  1240.      int *filesize;
  1241.      int highest_index;
  1242. {
  1243.   register int i;
  1244.  
  1245.   *filesize = 0;
  1246.   for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
  1247.     *filesize += sparsearray[i].numbytes;
  1248. }
  1249.  
  1250. /*
  1251.  * Make a header block for the file  name  whose stat info is  st .
  1252.  * Return header pointer for success, NULL if the name is too long.
  1253.  */
  1254. union record *
  1255. start_header (name, st)
  1256.      char *name;
  1257.      register struct stat *st;
  1258. {
  1259.   register union record *header;
  1260.  
  1261.   if (strlen (name) >= NAMSIZ)
  1262.     write_long (name, LF_LONGNAME);
  1263.  
  1264.   header = (union record *) findrec ();
  1265.   bzero (header->charptr, sizeof (*header));    /* XXX speed up */
  1266.  
  1267.   /*
  1268.      * Check the file name and put it in the record.
  1269.      */
  1270.   if (!f_absolute_paths)
  1271.     {
  1272.       static int warned_once = 0;
  1273. #if defined(__MSDOS__) || defined(WINDOWSNT)
  1274.       if (name[1] == ':')
  1275.     {
  1276.       name += 2;
  1277.       if (!warned_once++)
  1278.         msg ("Removing drive spec from names in the archive");
  1279.     }
  1280. #endif
  1281.       while ('/' == *name)
  1282.     {
  1283.       name++;        /* Force relative path */
  1284.       if (!warned_once++)
  1285.         msg ("Removing leading / from absolute path names in the archive.");
  1286.     }
  1287.     }
  1288.   current_file_name = name;
  1289.   strncpy (header->header.arch_name, name, NAMSIZ);
  1290.   header->header.arch_name[NAMSIZ - 1] = '\0';
  1291.  
  1292.   to_oct ((long) (f_oldarch ? (st->st_mode & 07777) : st->st_mode),
  1293.       8, header->header.mode);
  1294.   to_oct ((long) st->st_uid, 8, header->header.uid);
  1295.   to_oct ((long) st->st_gid, 8, header->header.gid);
  1296.   to_oct ((long) st->st_size, 1 + 12, header->header.size);
  1297.   to_oct ((long) st->st_mtime, 1 + 12, header->header.mtime);
  1298.   /* header->header.linkflag is left as null */
  1299.   if (f_gnudump)
  1300.     {
  1301.       to_oct ((long) st->st_atime, 1 + 12, header->header.atime);
  1302.       to_oct ((long) st->st_ctime, 1 + 12, header->header.ctime);
  1303.     }
  1304.  
  1305. #ifndef NONAMES
  1306.   /* Fill in new Unix Standard fields if desired. */
  1307.   if (f_standard)
  1308.     {
  1309.       header->header.linkflag = LF_NORMAL;    /* New default */
  1310.       strcpy (header->header.magic, TMAGIC);    /* Mark as Unix Std */
  1311.       finduname (header->header.uname, st->st_uid);
  1312.       findgname (header->header.gname, st->st_gid);
  1313.     }
  1314. #endif
  1315.   return header;
  1316. }
  1317.  
  1318. /*
  1319.  * Finish off a filled-in header block and write it out.
  1320.  * We also print the file name and/or full info if verbose is on.
  1321.  */
  1322. void
  1323. finish_header (header)
  1324.      register union record *header;
  1325. {
  1326.   register int i, sum;
  1327.   register char *p;
  1328.  
  1329.   bcopy (CHKBLANKS, header->header.chksum, sizeof (header->header.chksum));
  1330.  
  1331.   sum = 0;
  1332.   p = header->charptr;
  1333.   for (i = sizeof (*header); --i >= 0;)
  1334.     {
  1335.       /*
  1336.          * We can't use unsigned char here because of old compilers,
  1337.          * e.g. V7.
  1338.          */
  1339.       sum += 0xFF & *p++;
  1340.     }
  1341.  
  1342.   /*
  1343.      * Fill in the checksum field.  It's formatted differently
  1344.      * from the other fields:  it has [6] digits, a null, then a
  1345.      * space -- rather than digits, a space, then a null.
  1346.      * We use to_oct then write the null in over to_oct's space.
  1347.      * The final space is already there, from checksumming, and
  1348.      * to_oct doesn't modify it.
  1349.      *
  1350.      * This is a fast way to do:
  1351.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1352.      */
  1353.   to_oct ((long) sum, 8, header->header.chksum);
  1354.   header->header.chksum[6] = '\0';    /* Zap the space */
  1355.  
  1356.   userec (header);
  1357.  
  1358.   if (f_verbose)
  1359.     {
  1360.       extern union record *head;/* Points to current tape header */
  1361.       extern int head_standard;    /* Tape header is in ANSI format */
  1362.  
  1363.       /* These globals are parameters to print_header, sigh */
  1364.       head = header;
  1365.       /* hstat is already set up */
  1366.       head_standard = f_standard;
  1367.       print_header ();
  1368.     }
  1369.  
  1370.   return;
  1371. }
  1372.  
  1373.  
  1374. /*
  1375.  * Quick and dirty octal conversion.
  1376.  * Converts long "value" into a "digs"-digit field at "where",
  1377.  * including a trailing space and room for a null.  "digs"==3 means
  1378.  * 1 digit, a space, and room for a null.
  1379.  *
  1380.  * We assume the trailing null is already there and don't fill it in.
  1381.  * This fact is used by start_header and finish_header, so don't change it!
  1382.  *
  1383.  * This should be equivalent to:
  1384.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1385.  * except that sprintf fills in the trailing null and we don't.
  1386.  */
  1387. void
  1388. to_oct (value, digs, where)
  1389.      register long value;
  1390.      register int digs;
  1391.      register char *where;
  1392. {
  1393.  
  1394.   --digs;            /* Trailing null slot is left alone */
  1395.   where[--digs] = ' ';        /* Put in the space, though */
  1396.  
  1397.   /* Produce the digits -- at least one */
  1398.   do
  1399.     {
  1400.       where[--digs] = '0' + (char) (value & 7);    /* one octal digit */
  1401.       value >>= 3;
  1402.     }
  1403.   while (digs > 0 && value != 0);
  1404.  
  1405.   /* Leading spaces, if necessary */
  1406.   while (digs > 0)
  1407.     where[--digs] = ' ';
  1408.  
  1409. }
  1410.  
  1411.  
  1412. /*
  1413.  * Write the EOT record(s).
  1414.  * We actually zero at least one record, through the end of the block.
  1415.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1416.  */
  1417. void
  1418. write_eot ()
  1419. {
  1420.   union record *p;
  1421.   int bufsize;
  1422.  
  1423.   p = findrec ();
  1424.   if (p)
  1425.     {
  1426.       bufsize = endofrecs ()->charptr - p->charptr;
  1427.       bzero (p->charptr, bufsize);
  1428.       userec (p);
  1429.     }
  1430. }
  1431.  
  1432. /* Write a LF_LONGLINK or LF_LONGNAME record. */
  1433. void
  1434. write_long (p, type)
  1435.      char *p;
  1436.      char type;
  1437. {
  1438.   int size = strlen (p) + 1;
  1439.   int bufsize;
  1440.   union record *header;
  1441.   struct stat foo;
  1442.  
  1443.  
  1444.   bzero (&foo, sizeof foo);
  1445.   foo.st_size = size;
  1446.  
  1447.   header = start_header ("././@LongLink", &foo);
  1448.   header->header.linkflag = type;
  1449.   finish_header (header);
  1450.  
  1451.   header = findrec ();
  1452.  
  1453.   bufsize = endofrecs ()->charptr - header->charptr;
  1454.  
  1455.   while (bufsize < size)
  1456.     {
  1457.       bcopy (p, header->charptr, bufsize);
  1458.       p += bufsize;
  1459.       size -= bufsize;
  1460.       userec (header + (bufsize - 1) / RECORDSIZE);
  1461.       header = findrec ();
  1462.       bufsize = endofrecs ()->charptr - header->charptr;
  1463.     }
  1464.   bcopy (p, header->charptr, size);
  1465.   bzero (header->charptr + size, bufsize - size);
  1466.   userec (header + (size - 1) / RECORDSIZE);
  1467. }
  1468.